package com.qisu.socket.server;

import java.nio.ByteOrder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

import com.qisu.socket.server.handlers.CommandHandler;
import com.qisu.socket.server.handlers.CustomChannelReader;
import com.qisu.socket.server.handlers.SharableByteArrayDecoder;
import com.qisu.socket.server.handlers.SharableByteArrayEncoder;

import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.FixedLengthFrameDecoder;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.logging.LoggingHandler;

/**
 * 
 * @author alsan
 *
 */
@Component
@Configuration
public class ServerChannelInitializer extends ChannelInitializer<SocketChannel> {
	private ChannelHandlerAdapter _lenDecoder = null;

	@Value("${packet.length.lengthType}")
	String _lenFieldType;
	@Value("${packet.length.orderType}")
	String _byteOrder;
	@Value("${packet.length.max}")
	int _maxFrameLen;
	@Value("${packet.length.pos}")
	int _lenFieldPos;
	@Value("${packet.length.length}")
	int _lenFieldLen;
	@Value("${packet.length.adjust}")
	int _lenAdjustment;
	@Value("${packet.length.strip}")
	int _byteStrip;
	@Value("${packet.length.failFast}")
	boolean _failFast;

	@Autowired
	private SharableByteArrayDecoder _byteArrayDecoder;
	@Autowired
	private SharableByteArrayEncoder _byteArrayEncoder;
	@Autowired
	private CommandHandler _cmdHandler;

	private CustomChannelReader _custChannelReader;

	public CustomChannelReader getCustomChannelReader() {
		return _custChannelReader;
	}

	public void setCustomChannelReader(CustomChannelReader custChannelreader) {
		_custChannelReader = custChannelreader;
	}

	@Override
	protected void initChannel(SocketChannel socketChannel) throws Exception {

		if (null == _custChannelReader) {
			ChannelPipeline pipeline = socketChannel.pipeline().addFirst(new LoggingHandler());
			
			if (_lenFieldType.equalsIgnoreCase("variable")) {
				ByteOrder byteOrder = _byteOrder.equalsIgnoreCase("LITTLE_ENDIAN") ? ByteOrder.LITTLE_ENDIAN
						: ByteOrder.BIG_ENDIAN;

				 _lenDecoder = new LengthFieldBasedFrameDecoder(byteOrder,
				 _maxFrameLen, _lenFieldPos, _lenFieldLen, _lenAdjustment,
				 _byteStrip, _failFast);
				 
			} else if (_lenFieldType.equalsIgnoreCase("FIXEDLEN")) {
				_lenDecoder = new FixedLengthFrameDecoder(_lenFieldLen);
			}

			pipeline.addLast(_lenDecoder);
			pipeline.addLast(_byteArrayDecoder).addLast(_byteArrayEncoder).addLast(_cmdHandler);
			
		} else {
			_custChannelReader.initChannel(socketChannel);
		}
	}

}
